在每一次請求api都要帶上token讓後端來驗證這個請求是否是有經過認證的,若沒有驗證過就不能讓它去訪問api取得或是更改資料,請求圖如下。

JWT(JSON Web Token)是一個網路開放標準(RFC 7519)是無狀態性的,通常利用JWT來對使用者進行身分驗證。
JWT 是一組字串,透過(.)切分成三個為 Base64 編碼的部分:
Signature 是這樣組成
HMACSHA256(
base64(header) + "." +
base64(payload),
secret)
JWT的簽發與驗證都須使用這個 secret key,當其他人得知這個 secret,那就意味著我們可以自己簽發JWT ,因此在任何情況都不應該外流。
前端存取api時必須在header帶上Authorization: Basic xxxxxx  到後端進行身分驗證
<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>0.9.1</version>
</dependency>
JwtTokenUtils.java@Component
public class JwtToken implements Serializable {
    private static final long EXPIRATION_TIME = 1 * 60 * 1000;
    /**
     * JWT SECRET KEY
     */
    private static final String SECRET = "learn to dance in the rain";
    /**
     * 簽發JWT
     */
    public String generateToken(HashMap<String, String> userDetails) {
        Map<String, Object> claims = new HashMap<>();
        claims.put( "userName", userDetails.get("userName") );
        return Jwts.builder()
                .setClaims( claims )
                .setExpiration( new Date( Instant.now().toEpochMilli() + EXPIRATION_TIME  ) )
                .signWith( SignatureAlgorithm.HS512, SECRET )
                .compact();
    }
    /**
     * 驗證JWT
     */
    public void validateToken(String token) throws AuthException {
        try {
            Jwts.parser()
                    .setSigningKey( SECRET )
                    .parseClaimsJws( token );
        } catch (SignatureException e) {
            throw new AuthException("Invalid JWT signature.");
        }
        catch (MalformedJwtException e) {
            throw new AuthException("Invalid JWT token.");
        }
        catch (ExpiredJwtException e) {
            throw new AuthException("Expired JWT token");
        }
        catch (UnsupportedJwtException e) {
            throw new AuthException("Unsupported JWT token");
        }
        catch (IllegalArgumentException e) {
            throw new AuthException("JWT token compact of handler are invalid");
        }
    }
}
[POST]/api/login ,接收使用者登入@RestController
@RequestMapping("/api")
public class TodoController {
@PostMapping("/login")
public ResponseEntity login(@RequestBody HashMap <String, String> user) {
    JwtToken jwtToken = new JwtToken();
    String token = jwtToken.generateToken(user); // 取得token
    return ResponseEntity.status(HttpStatus.OK).body(token);
   }
}
用POSTMAN串接[POST]/api/login 會回傳一組token
可以將token放置jwt.io/ 裡去解碼出來看看token藏了哪些資訊
假設我們現在存取某一支api [GET]/api/hello,要在header中帶入Authorization Basic tokenxxxxx ,並回傳結果。
@RestController
@RequestMapping("/api")
public class TodoController {
@GetMapping("/hello")
public ResponseEntity hello(@RequestHeader("Authorization") String au) {
    String token = au.substring(6);
    JwtToken jwtToken = new JwtToken();
    try {
        jwtToken.validateToken(token);
    } catch (AuthException e) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getMessage());
    }
    return ResponseEntity.status(HttpStatus.OK).body("Hello CaiLi");
  }
}
接著用POSTMAN存取[GET]/api/hello ,回傳status code 200 OK
因為token 的過期時間為一分鐘,一分鐘後再請求一次,則會回傳403 Forbidden
JWT(JSON Web Token) — 原理介紹
Spring Boot Security 整合JWT實現無狀態的分散式API介面